package mvc.controller;


import mvc.exception.AgeException;
import mvc.exception.MyException;
import mvc.exception.NameException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.ModelAndView;
import mvc.pojo.Student;

import java.util.Objects;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/11/11 22:26
 */
@Controller
public class MyController {
    /**
     *  /开头都会被前端控制器所拦截，由配置前端控制器时所指定
     * @return
     */
    @RequestMapping(value = "/model",method = RequestMethod.GET)
    public ModelAndView model() {
        ModelAndView modelAndView = new ModelAndView();
        // modelAndView表示请求的处理结果
        //  modelAndView.addObject底层是request.setAttribute
        modelAndView.addObject("czk","nzq");
        // 指定视图 框架对视图执行foward操作，request.getRequestDispather("/show.jsp").forward()....
        modelAndView.setViewName("/show");
        System.out.println("czk");
        return modelAndView;
    }

    /**
     * 框架接收请求参数
     * 1 使用request对象接收请求参数
     *   String nameStr=request.getParameter("name")
     *   String ageStr=request.getParameter("age")
     * 2 Springmvc通过dispacherServlet抵用Controller的receive方法
     *  调用方法时，按名称对应将参数赋值
     *  其会提供类型转换的功能，能爸Str转换成int、long、float、double等类型
     *  注意：400表示提供的参数异常，方法类型匹配参数异常
     *  Integer 可以接收为null的值，int则不行
     * @param name
     * @param age
     * @return
     */
    @GetMapping("/receive")
    public ModelAndView receive(String name,Integer age){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("name",name);
        modelAndView.addObject("age",age);
        return modelAndView;
    }

    /**
     * RequestParam解决参数名称不一致的问题
     * boolean required() default true表示请求中必须包含此参数，没有就会报400错误
     * @param name
     * @return
     */
    @GetMapping("/param")
    public ModelAndView receiveParam(@RequestParam(value = "rname",required = false) String name){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("name",name);
        return modelAndView;
    }

    /**
     * 框架会创建形参的java对象，调用其无参数构造方法
     * 调用其set方法为其赋值
     * @param student
     * @return
     */
    @GetMapping("/object")
    public ModelAndView student(Student student){
        System.out.println(student.getAge());
        System.out.println(student.getName());
        ModelAndView modelAndView=new ModelAndView();
        return modelAndView;
    }

    /**
     * 返回值为string->此时表示转发页面，将页面转发到指定的页面
     * @return
     */
    @GetMapping("/shop")
    public String shop(ServletWebRequest request){
        System.out.println(request.getParameter("czk"));
        // 设置属性scope，1代表request域，2代表session域
        request.setAttribute("czk","czk",1);
        return "/shop";
    }

    /**
     *
     * @param name
     * @param age
     */
    @GetMapping("/ajax")
    public void ajax(String name,Integer age,ServletWebRequest request){
        Student student=new Student();
        student.setName(name);
        student.setAge(age);
        // 转成json
        String json="{"+"name:"+student.getName()+",age:"+student.getAge();
        // 写回页面

    }

    /**
     * <mvc:annotation-driven></mvc:annotation-driven> 注解驱动，实现功能是完成java对象到json。xml、text二进制等数据格式的转换
     * HttpMessageConveter接口：消息转换器
     * 功能：定义了java转为json,xml等数据格式的方法，
     *  方法：1 boolean canWrite(Class<?> var1, @Nullable MediaType var2);->检查处理器方法的返回值，能不能转成var2表示的数据格式
     *  MediaType表示数据格式，有很多种，如果能转成json，返回true
     *       2 void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
     *       把处理器的方法的返回值对象，调用jackson中的ObjectMapper转为json字符串
     *       常用的转换实现类MappingJackson2HttpMessageConverter-》转json的消息转换器
     *       MappingJackson2HttpMessageConverter->转为string的消息转换器
     * @return
     */
    @GetMapping("/objectt")
    /**
     * ResponseBody通过httpServletResponse输出数据，响应ajax的请求
     */
    @ResponseBody
    /**
     * 返回值为对象的框架处理流程
     * 1框架会把返回的对象，调用Arraylist<HttpMessageConverter>中每个类的canWrite()方法
     *  检查哪个httpMessageConverter的实现类能够处理返回的对象类型-》json是MappingToJaskson2MessageConverter
     * 2框架会调用合适的实现类的write()方法，将其转为合适的对象格式</>
     * 3 框架会调用@ResponseBody把结果输出达到浏览器，ajax请求处理完成
     */
    public Student object(){
        return new Student();
    }

    /**
     * 区分返回值是数据还是视图，看是否有ResponseBody注解，有则是数据，没有则是视图
     * 返回值为string时的消息转换器为StringHttpMessageConverter,默认的编码是iso-8859-1导致中文乱码
     * 解决方案是添加属性produce，指定编码
     * @return
     */
    @ResponseBody
    @GetMapping(value = "/string",produces = "text/plain;charset=utf-8")
    public String doString(){
        return "czk";
    }

    /**
     *
     * @param name
     * @param age
     * @return
     * @throws MyException
     */
    @GetMapping("/ex")
    @ResponseBody
    public String ex(String name,Integer age) throws MyException {
        if (!Objects.equals(name,"czk")){
            throw new NameException("姓名错误");
        }
        if (!Objects.equals(age,15)){
            throw new AgeException("年龄错误");
        }
        return "登陆成功";
    }
}
